import sys
import logging
log = logging.getLogger(__name__)

try:
    from hashlib import md5
except ImportError:
    from md5 import md5

class AuthenticationChecker(object):
    '''Base class for Authority AuthenticationChecker objects
    
    '''
    def __init__(self, checker_opts = None):
        checker_opts = checker_opts or {}
        self.options = checker_opts
        
    def check_credentials(self, cred):
        raise NotImplementedError
        
    def initialize_storage(self):
        raise NotImplementedError

    
class MatchChecker(AuthenticationChecker):
    '''Checks that the username and password match.
    
    Trivial implementation of an AuthenticationChecker.
    '''
    
    def check_credentials(self, cred):
        if cred['user'] == cred['password']:
            return True
        else:
            return False
            
            
class HtpasswdChecker(AuthenticationChecker):
    '''Checks authentication credentials against a apache-style
    "htpasswd" file.
    
    NOTE: THIS IS NOT FINISHED...DO NOT EXPECT IT TO WORK YET!
    
    NOTE: Not Apache compatible!
    Apache uses their own MD5 implementation...this uses the Python one!
    
    NOTE: This checker (at least for now) will load authentication info 
    only when first loaded, so the app will have to be restarted in order 
    to see changes!
    
    config options:
    authority.method.authfile -- path to htpasswd file to check
    authority.method.hashtype -- hash function with which passwords are encrypted
    (not yet supported...use md5 for now)
    '''
    def __init__(self, checker_opts = None):
        AuthenticationChecker.__init__(self, checker_opts)
        
        #check that required config options are available, or set defaults
        # TODO
        
        
        # finish initializing class
        self.authfilename = self.options.get('authfile', './authority_htpasswd')
        
        self.authdict = {}
        authfile = open(self.authfilename, 'r')
        for userline in authfile:
            user, passwdhash = userline.strip().split(':')
            self.authdict[user] = passwdhash
        
        authfile.close()
        
        
    def check_credentials(self, cred):
        #~ raise NotImplementedError # temporary
        
        user, passwd = cred['user'], cred['password']
        
        if self.authdict.has_key(user):
            m = md5()
            m.update(passwd)
            passwd_hash = m.hexdigest()
            if passwd_hash == self.authdict[user]:
                return True
            
            
        return False
        
    def initialize_storage(self):
        raise NotImplementedError
        

if sys.platform == 'win32':
    from win32security import LogonUser 
    from win32security import LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT
    from win32security import error as LogonError


    class SMBChecker(AuthenticationChecker):
        '''Check authentication using Windows Auth
        
        TODO: this almost works, but needs to get domain info either from 
        user or from config
        '''
        
        def __init__(self, checker_opts = None):
            AuthenticationChecker.__init__(self, checker_opts)
            
            # TODO: more initialization?
            # set default domain?  config-provided or user-provided?

        def check_credentials(self, cred):
            try:
                cred['domain'] = 'your_domain_here'
                token = LogonUser(cred['user'],
                                  cred['domain'],
                                  cred['password'],
                                  LOGON32_LOGON_NETWORK,
                                  LOGON32_PROVIDER_DEFAULT)
            except LogonError:
                return False
            else:
                return bool(token)   # usually True

        def initialize_storage(self):
            raise NotImplementedError
        